#ifndef MEMPOOL_H
#define MEMPOOL_H

#include <iostream>
#include <vector>

#include "CommonDefines.h"

using namespace std;

typedef void* CURSOR;

class CGlobalMemPool {
public:
	~CGlobalMemPool();
	void Apply(size_t index, npINTPOINTER* head, npINTPOINTER* tail, size_t* chunk_num, npINTPOINTER* local_pool_cursor);
	void RecycleFreeChunks(size_t index, void* freeChunkHead, CURSOR cursor);
	void RecycleLocalPool(void** freeChunkHeadArray,
			               void** freeChunkTailArray,
			               MemBlock** blockHeadArray,
			               MemBlock** blockTailArray,
			               CURSOR* cursor,
			               size_t* freeChunkCountArray);

	static CGlobalMemPool* GetInstance();
	static void ReleaseInstance();
private:
	typedef struct _ST_ALLOC_UNIT{
		_ST_ALLOC_UNIT()
		: cursor(NULL)
		, chunk_num(0)
		, local_pool_cursor(NULL){}

		_ST_ALLOC_UNIT(CURSOR _cursor, size_t _chunk_num, CURSOR _local_pool_cursor = NULL)
		: cursor(_cursor)
		, chunk_num(_chunk_num)
		, local_pool_cursor(_local_pool_cursor){}

		_ST_ALLOC_UNIT(const _ST_ALLOC_UNIT& allocUnit)
		: cursor(allocUnit.cursor)
		, chunk_num(allocUnit.chunk_num)
		, local_pool_cursor(allocUnit.local_pool_cursor){}

		CURSOR cursor;
		size_t chunk_num;
		CURSOR local_pool_cursor;
	}ST_ALLOC_UNIT;

	typedef vector<ST_ALLOC_UNIT> AllocUnitStack;

	CGlobalMemPool();
	static CGlobalMemPool* mp_Instance;
	void* mp_freeChunkHeadArray[EN_BIN_INDEX_MAX];
	MemBlock* mp_blockHeadArray[EN_BIN_INDEX_MAX];
	size_t m_freeChunkCountArray[EN_BIN_INDEX_MAX];
	pthread_mutex_t* mp_mutex;

	AllocUnitStack m_allocInfo[EN_BIN_INDEX_MAX]; // alloc info for alloc unit in GP
};

class CLocalMempool {
public:
	void* New(std::size_t size);
	void Delete(void* ptrObj, std::size_t size);
	~CLocalMempool();
	CLocalMempool();
private:
	size_t indexMapper(std::size_t size);
private:
	void* mp_freeChunkHeadArray[EN_BIN_INDEX_MAX]; // free chunk head list array
	void* mp_freeChunkTailArray[EN_BIN_INDEX_MAX]; // free chunk tail list array
	MemBlock* mp_blockHeadArray[EN_BIN_INDEX_MAX]; // free chunk block head list array
	MemBlock* mp_blockTailArray[EN_BIN_INDEX_MAX]; // free chunk block tail list array
	size_t m_freeChunkCountArray[EN_BIN_INDEX_MAX]; // free chunk number in each free chunk list

	CURSOR m_cursor[EN_BIN_INDEX_MAX]; // the cursor for reduce memory drift
};


#endif //MEMPOOL_H
